/** \file translatorHelper.h
* A helper class for translating a ProgGraph into g-mini Graph or vise versa
*/

#ifndef _HELPER_TRANSLATORS_H
#define _HELPER_TRANSLATORS_H

#include "graph.h"
#include "gminiGraph.h"
#include <map>
#include "newGraph.h"

class ForwardGraphTranslator
{
private:
	typedef map<Node *,NewGraph::ProgNode *> NodesCorrespondenceMap;
	typedef pair<Node *,NewGraph::ProgNode *> NodesCorrespondencePair;

	GminiGraph * our_graph;
	NewGraph * new_graph;
	NodesCorrespondenceMap corrMap;
	
	NodeTypeInterface * getEquivalentDecorator(Node * node);
	NewGraph::ProgNode * createNode(Node * node);
	NodeTypeInterface * getVariableDecorator(string variableName)
	{
		VariablesMap::iterator it=new_graph->varMap.find(variableName);
		if(it!=new_graph->varMap.end())
			return it->second.type;
		return NULL; //must not reach here if every variable is declared before being used
	}
	NewGraph::ProgNode * insertNode(Node * node)
	{
		NewGraph::ProgNode * node_eq= createNode(node);
		corrMap.insert(NodesCorrespondencePair(node,node_eq));
		new_graph->addNode(node_eq);
		return node_eq;
	}
	NewGraph::ProgNode * getCorrespondingNode(Node * node)
	{
		NodesCorrespondenceMap::iterator it=corrMap.find(node);
		if(it!=corrMap.end())
			return it->second;
		return NULL; //must not reach here if every variable is declared before being used
	}
	
public:
	ForwardGraphTranslator(GminiGraph * graph1): our_graph(graph1), new_graph(new NewGraph()) {}
	void translateAndInsert(Node* node);
	void translateAndInsert(Edge* edge);
	NewGraph * getTranslatedGraph()
	{
		return new_graph;
	}
};

/**
* \class BackwardGraphFactory
* \author Layale Constantine & Jad Makhlouta
* \brief implements a translation class for ProgGraph into Graph
*
*/
class BackwardGraphTranslator
{
private:
	typedef map<NewGraph::ProgNode *, Node *> NodesCorrespondenceMap;
	typedef pair<NewGraph::ProgNode *, Node *> NodesCorrespondencePair;
	NewGraph * our_graph;//<! ProgGraph to translate
	GminiGraph * new_graph; //<! G-mini graph, a translation of ProgGraph
	NodesCorrespondenceMap corrMap;//<!A hash table for a ProgNode and its translation to g-mini Node


	/*
	*\brief inserts a ProgNode and its translation into the hash table
	*
	*/
	void insertNode(NewGraph::ProgNode *  node, Node * node_eq)
	{
		corrMap.insert(NodesCorrespondencePair(node,node_eq));

	}

	/*
	*\brief searches the hash table for the g-mini Node translation of a given ProgNode
	*
	*\returns g-mini Node pointer or NULL if not found in hash
	*/
	Node * getCorrespondingNode(NewGraph::ProgNode * n)
	{
		NodesCorrespondenceMap::iterator it=corrMap.find(n);
		if(it!=corrMap.end())
			return it->second;
		return NULL; //must not reach here if every variable is declared before being used
	}

public:
	BackwardGraphTranslator(NewGraph * graph1): our_graph(graph1), new_graph(new GminiGraph()) {}
	Node * translateAndInsert(NewGraph::ProgNode * n);
	void translateAndInsert(NewGraph::ProgEdge * edge);
	Node * createTypeBranch(NodeTypeInterface * dec);
	GminiGraph * getTranslatedGraph()
	{
		return new_graph;
	}
};

#endif
